package com.soft.link.Interceptor;

import com.alibaba.fastjson.JSONObject;
import com.soft.link.annotation.UserCheck;
import com.soft.link.impl.RedisService;
import com.soft.link.utils.AES;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * company 重庆庆云石油工程技术有限责任公司
 * FileName CommonInterceptor
 * Package com.soft.link.Interceptor
 * Description App拦截器
 * author Administrator
 * create 2018-04-25 17:11
 * version V1.0
 */
@Component
public class AppInterceptor extends HandlerInterceptorAdapter {
    private static final String TIMEOUT = "/facade/login/timeout.htm";//超时跳转链接
    private static Logger logger = LoggerFactory.getLogger(AppInterceptor.class);

    @Autowired(required = false)
    private RedisService redisService;

    /**
     * 在业务处理器处理请求之前被调用：在Controller层执行前执行
     * 如果返回false  从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链
     * 如果返回true  执行下一个拦截器,直到所有的拦截器都执行完毕,再执行被拦截的Controller ,然后进入拦截器链,
     * 从最后一个拦截器往回执行所有的postHandle() ,接着再从最后一个拦截器往回执行所有的afterCompletion()
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        logger.info("App==============执行顺序: 1、preHandle================");
        String contextPath = request.getContextPath();
        HandlerMethod method = (HandlerMethod) handler;
        UserCheck auth = method.getMethodAnnotation(UserCheck.class);
        String url = request.getRequestURI();
        //aes解密移动终端传递过来的参数
        AES aes = new AES(AES.AES_KEY);
        String params = request.getParameter("params");
        if (StringUtils.isNotBlank(params)) {
            request.setAttribute("paramObj", aes.decrypt(params.replace("%2B", "+").replace(" ", "+")));
        }
        logger.info("参数：" + JSONObject.toJSONString(request.getParameterMap()));
        logger.info("headers：" + JSONObject.toJSONString(getHeadersInfo(request)));
        if (auth == null) {
            logger.info("app管理端接口，登陆无需验证token。接口地址：" + url);
            return true;
        } else {
            logger.info("移动终端接口，需要验证token。接口地址：" + url);
            String token = request.getParameter("token");
            if (redisService.exists(token)) {
                String tsUser = redisService.get(token);
                return true;
            }
            response.sendRedirect(contextPath + TIMEOUT);
            return false;
        }

    }

    /**
     * 在业务处理器处理请求执行完成后,生成视图之前执行的动作：在Controller层执行后执行，生成jsp前执行
     * 可在modelAndView中加入数据，比如当前时间
     */
    @Override
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
        logger.info("App==============执行顺序: 2、postHandle================");
    }

    /**
     * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等
     * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion()
     */
    @Override
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        logger.info("App==============执行顺序: 3、afterCompletion================");
    }

    private Map<String, String> getHeadersInfo(HttpServletRequest request) {
        Map<String, String> map = new HashMap<String, String>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }
}
